package com.yhsimon.realm.member.scheduled;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yhsimon.realm.member.entity.user.SeckillBeanActivityEntity;
import com.yhsimon.realm.member.service.SeckillBeanActivityService;
import com.yhsimon.realm.member.service.SeckillService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @author YHSimon
 */
@Slf4j
@Service
public class SeckillBeanActivityScheduled {

    private static final String SECKILL_BEAN_LOCK_PREFIX = "seckill:bean:lock:";

    @Autowired
    private SeckillService seckillService;

    @Autowired
    private SeckillBeanActivityService beanActivityService;

    @Autowired
    private RedissonClient redissonClient;

    @PostConstruct
    private void initUploadSeckillBeanActivity() {
        log.info("SeckillBeanActivityScheduled: initUploadSeckillBeanActivity: start...");
        uploadSeckillBeanActivity();
        log.info("SeckillBeanActivityScheduled: initUploadSeckillBeanActivity: end...");
    }

    @Scheduled(cron = "0 0 * * * ?")
    // @Scheduled(cron = "0 0/5 * * * ?")
    public void uploadSeckillBeanActivity() {
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startTime = now.withMinute(0).withSecond(0).withNano(0);
        LocalDateTime endTime = startTime.plusHours(1).minusNanos(1);
        Date startDateAsDate = Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant());
        Date endDateAsDate = Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant());
        String sessionName = LocalDate.now() + "-" + now.getHour();

        // 获取分布式锁
        String lockKey = SECKILL_BEAN_LOCK_PREFIX + sessionName;
        RLock lock = redissonClient.getLock(lockKey);
        try {
            if (lock.tryLock()) {
                lock.lock(1, TimeUnit.MINUTES);
                log.info("SeckillBeanActivityScheduled: uploadSeckillBeanActivity: 成功获取分布式锁: {}, 当前执行任务的线程号ID: {}", lockKey, Thread.currentThread().getId());
                // 缓存仙豆活动信息
                SeckillBeanActivityEntity seckillBeanActivityEntity = SeckillBeanActivityEntity.builder()
                        .seckillCount(10)
                        .seckillLimit(1)
                        .beanCount(10)
                        .startTime(startDateAsDate)
                        .endTime(endDateAsDate)
                        .sessionName(sessionName)
                        .build();
                log.info("SeckillBeanActivityScheduled: uploadSeckillBeanActivity: 信息如下: {}", seckillBeanActivityEntity);
                seckillService.uploadSeckillBeanActivity(seckillBeanActivityEntity);
                // 落盘
                if (!beanActivityService.exists(new QueryWrapper<SeckillBeanActivityEntity>().eq("session_name", seckillBeanActivityEntity.getSessionName()))) {
                    beanActivityService.save(seckillBeanActivityEntity);
                } else {
                    log.info("SeckillBeanActivityScheduled: uploadSeckillBeanActivity: 数据库中已有仙豆活动信息, 信息如下: {}", seckillBeanActivityEntity);
                }
            } else {
                log.info("SeckillBeanActivityScheduled: uploadSeckillBeanActivity: 无法获取分布式锁: {}, 当前执行任务的线程号ID: {}", lockKey, Thread.currentThread().getId());
            }

        } catch (Exception e) {
            log.error("SeckillBeanActivityScheduled: uploadSeckillBeanActivity: encountered an exception: {}", e.getMessage());
        } finally {
            if (lock.isHeldByCurrentThread()){
                lock.unlock();
                log.info("SeckillBeanActivityScheduled: uploadSeckillBeanActivity: 成功释放分布式锁: {}, 当前执行任务的线程号ID: {}", lockKey, Thread.currentThread().getId());
            }
        }
    }


    /**
     * 定时监控仙豆活动是否上线
     */
    @Scheduled(cron = "0 10,20,30,40,50 * * * ?")
    public void monitorSeckillBeanActivityInfo() {
        log.info("SeckillBeanActivityScheduled: monitorSeckillBeanActivityInfo: start...");
        uploadSeckillBeanActivity();
        log.info("SeckillBeanActivityScheduled: monitorSeckillBeanActivityInfo: end...");
    }


}
